1. Field of the Invention
The present invention generally relates to a dynamic compiling environment using a virtual machine, and, more particularly, to methods and apparatuses for dynamically generating an executable machine code using a Just-In-Time (JIT) compiler.
2. Description of the Related Art
In a software execution environment in which an analyzer of a virtual machine is used, an executable machine code that is dynamically generated using a JIT compiler while executing software is used to improve the execution performance of the software. The executable machine code may access necessary data by using a Program Counter (PC)-relative load instruction or store instruction. When a fixed-length instruction is used, a range of memory, which can be accessed using the corresponding instruction, is limited according to an offset size of the instruction. Thus, executable code is generated such that an instruction and data are intertwined in the executable code.
Accordingly, so that a microprocessor does not recognize data as an instruction, a branch instruction, which causes a next instruction to be executed by skipping the corresponding data area, has to be inserted in an address right before the data area. That is, in order to connect a first code area and a second code area that are separated by a data area, a branch instruction is inserted at the end of the first code area. When the instruction and the data are arranged too sporadically, the performance of the cache memory is decreased, and further, too many branch instructions are inserted, thereby deteriorating the quality of the executable code.
In a microprocessor in which length of an instruction is fixed to a data bus length of a memory, a space for storing a memory address per an instruction is insufficient. Thus two types of instructions are provided in order to branch to a predetermined address during execution of a program. The first type is a load-based branch instruction. According to the load-based branch instruction, a branching object address or address to be branched stored as data is referenced via a PC-relative offset and is directly input to the PC. The second type is a PC-relative branch instruction, which performs branching to an address corresponding to a PC-relative offset. Regarding the load-based branch instruction, a branching object address is stored in a memory as data, and thus branching to all memory areas is possible. However, in this case, another memory space for storing the branching object address is additionally needed, and the memory storing the branching object address needs to be referenced during execution, and thus additional execution time is required. Regarding the PC-relative branch instruction, a branching object is limited to a PC-relative offset range but memory space for storing a branching object address is saved, and memory is not referenced, and thus branching requires little time.
In an environment where a executable machine code is dynamically generated as in a JIT compiler, in order to optimize a memory environment, there is an occasion when a series of instructions and data are generated, and then memory space for executable code may be allocated according to size of blocks of the generated instructions and data. In this case, an address of a branch instruction is not determined at a point when the branch instruction is generated, and thus a distance between the branch instruction and a branching object address is not known. Accordingly, if a branch instruction is required, first, a load-based branch instruction is generated and inserted into an instruction block, and then space for storing a branching object address is formed within an offset range of an instruction and the branching object address is input to the space. Later, after allocating memory space for executable code, from among the load-based branch instructions that are meanwhile generated, some load-based branch instructions whose branching objects exist within a PC-relative offset range are substituted with PC-relative branch instructions, which are relatively efficient branch instructions.
FIG. 1 illustrates switching from a load-based branch instruction to a PC-relative branch instruction in the above-described manner. Referring to FIG. 1, as a branching object 103 of a load-based instruction 101 is within a PC-relative branch instruction offset range 104, after memory for executable code is allocated, the load-based instruction 101 is substituted with a PC-relative branch instruction 111, and an offset of the substituted PC-relative branch instruction 111 is generated to indicate the branching object 103. In the above-described manner, two clock cycles consumed by one load-based branch instruction can be replaced with one clock cycle consumed by a PC-relative branch instruction, which means time can be saved this much. However, a space 102 where the branching object address of the load-based branch instruction has been stored still remains after the load-based branch instruction is substituted with a PC-relative branch instruction. Thus unnecessary space that is not used anymore is created. In order to remove this space from the executable code, the instruction and the data used by the instruction need to be rearranged so as to be continuous. Then positions of data become different, and thus an offset of the corresponding instruction needs to be readjusted, thereby decreasing efficiency.